package cn.com.easy.pay.weixinpay.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;

import cn.com.easy.dto.MessageDTO;
import cn.com.easy.exception.BusinessException;
import cn.com.easy.pay.weixinpay.config.WeixinPayConfig;
import cn.com.easy.utils.ResponseOutputUtils;

import com.tencent.common.Configure;
import com.tencent.common.Util;
import com.tencent.protocol.pay_query_protocol.ScanPayQueryReqData;
import com.tencent.protocol.pay_query_protocol.ScanPayQueryResData;
import com.tencent.service.ScanPayQueryService;

/**
 * 订单查询基础控制器
 * 
 * @author nibili 2017年5月12日
 * 
 */
public abstract class WeixinPayQueryBaseController {

	private Logger logger = LoggerFactory.getLogger(WeixinPayQueryBaseController.class);

	/** 订单查询服务类 ，sdk */
	private ScanPayQueryService scanPayQueryService;

	/**
	 * 获取微信支付配置<br/>
	 * 
	 * @param httpRequest
	 * @return
	 * @throws BusinessException
	 * @author nibili 2017年5月12日
	 */
	public abstract WeixinPayConfig getWeixinPayConfig(HttpServletRequest httpRequest) throws BusinessException;

	/**
	 * * 进行一次支付订单查询操作
	 * 
	 * @param outTradeNo
	 *            商户系统内部的订单号,32个字符内可包含字母, [确保在商户系统唯一]
	 * @param request
	 * @param response
	 * @param outTradeNo
	 * @author nibili 2017年5月12日
	 */
	@RequestMapping("/refund")
	public void payQuery(final HttpServletRequest request, final HttpServletResponse response, String outTradeNo) {
		try {
			WeixinPayConfig weixinPayConfig = getWeixinPayConfig(request);
			Configure configure = new Configure();
			configure.setKey(weixinPayConfig.getAppkey());
			configure.setAppID(weixinPayConfig.getAppid());
			configure.setMchID(weixinPayConfig.getMch_id());
			configure.setSubMchID(weixinPayConfig.getSubMchID());
			configure.setCertLocalPath(weixinPayConfig.getCertLocalPath());
			configure.setCertPassword(weixinPayConfig.getCertPassword());
			//
			scanPayQueryService = new ScanPayQueryService(configure);
			//
			ScanPayQueryReqData scanPayQueryReqData = new ScanPayQueryReqData(configure, "", outTradeNo);
			// 查询返回字段串
			String payQueryServiceResponseString = scanPayQueryService.request(scanPayQueryReqData);

			// 将从API返回的XML数据映射到Java对象
			ScanPayQueryResData scanPayQueryResData = (ScanPayQueryResData) Util.getObjectFromXML(payQueryServiceResponseString, ScanPayQueryResData.class);
			if (scanPayQueryResData == null || scanPayQueryResData.getReturn_code() == null) {
				// log.i("支付订单查询请求逻辑错误，请仔细检测传过去的每一个参数是否合法");
				this.onFailByReturnCodeError(request, response, scanPayQueryResData);
				return;
			}

			if (scanPayQueryResData.getReturn_code().equals("FAIL")) {
				// 注意：一般这里返回FAIL是出现系统级参数错误，请检测Post给API的数据是否规范合法
				// log.i("支付订单查询API系统返回失败，失败信息为：" +
				// scanPayQueryResData.getReturn_msg());
				this.onFailByReturnCodeFail(request, response, scanPayQueryResData);
				return;
			} else {
				if (scanPayQueryResData.getResult_code().equals("SUCCESS")) {// 业务层成功
					if (scanPayQueryResData.getTrade_state().equals("SUCCESS")) {
						// 表示查单结果为“支付成功”
						// log.i("查询到订单支付成功");
						this.onQuerySuccess(request, response, scanPayQueryResData);
						return;
					} else {
						// 支付不成功
						// log.i("查询到订单支付不成功");
						this.onQueryFail(request, response, scanPayQueryResData);
						return;
					}
				} else {
					// log.i("查询出错，错误码：" + scanPayQueryResData.getErr_code() +
					// "     错误信息：" + scanPayQueryResData.getErr_code_des());
					this.onQueryFail(request, response, scanPayQueryResData);
					return;
				}
			}
		} catch (BusinessException ex) {
			logger.error("订单查询发生异常(自定义异常):" + ex.getMessage(), ex);
			// 错误
			ResponseOutputUtils.renderJson(response, MessageDTO.newInstance("", false, ex.getMessage()));
		} catch (Exception ex) {
			logger.error("订单查询发生异常:" + ex.getMessage(), ex);
			// 错误
			ResponseOutputUtils.renderJson(response, MessageDTO.newInstance("", false, ex.getMessage()));
		}
	}

	/**
	 * 订单支付失败<br/>
	 * 例：支付失败
	 * 
	 * @param request
	 * @param response
	 * @param refundResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onQueryFail(HttpServletRequest request, HttpServletResponse response, ScanPayQueryResData scanPayQueryResData);

	/**
	 * 订单支付成功
	 * 
	 * @param request
	 * @param response
	 * @param scanPayQueryResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onQuerySuccess(HttpServletRequest request, HttpServletResponse response, ScanPayQueryResData scanPayQueryResData);

	/**
	 * API返回ReturnCode不合法，支付请求逻辑错误，请仔细检测传过去的每一个参数是否合法，或是看API能否被正常访问 <br/>
	 * 例：请检查每一个参数是否合法
	 * 
	 * @param request
	 * @param response
	 * @param scanPayQueryResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onFailByReturnCodeError(HttpServletRequest request, HttpServletResponse response, ScanPayQueryResData scanPayQueryResData);

	/**
	 * API返回ReturnCode为FAIL，支付API系统返回失败，请检测Post给API的数据是否规范合法 <br/>
	 * 例 ： 请检测Post给API的数据是否规范合法
	 * 
	 * @param request
	 * @param response
	 * @param scanPayQueryResData
	 * @author nibili 2017年5月12日
	 */
	public abstract void onFailByReturnCodeFail(HttpServletRequest request, HttpServletResponse response, ScanPayQueryResData scanPayQueryResData);

}
